
window.XBOX = (function (window, document, $) {
  'use strict';
  var xbox = {
    duplicate: false,
    media: {
      frames: {}
    },
    delays: {
      removeItem: {
        fade: 200,
        confirm: 100,
        events: 900,//tiene que ser mayor a fade, menos de 400 falla al ordenar items
      }
    }
  };

  xbox.init = function () {
    xbox.$xbox = $('.xbox');
    var $form = xbox.$xbox.closest('.xbox-form');
    if (!$form.length) {
      $form = xbox.$xbox.closest('form#post');
    }

    //Disable form submit on enter
    $form.on('keyup keypress', 'input', function (e) {
      var keyCode = e.which;
      if (keyCode === 13) {
        e.preventDefault();
        return false;
      }
    });

    $(window).resize(function () {
      if (viewport().width <= 850) {
        $('#post-body').addClass('xbox-columns-1');
      } else {
        $('#post-body').removeClass('xbox-columns-1');
      }
    }).resize();


    xbox.init_image_selector();
    xbox.init_tab();
    xbox.init_switcher();
    xbox.init_spinner();
    xbox.init_checkbox();
    xbox.init_dropdown();
    xbox.init_colorpicker();
    xbox.init_code_editor();
    xbox.init_sortable_preview_items();
    xbox.init_sortable_checkbox();
    xbox.init_sortable_repeatable_items();
    xbox.init_sortable_group_items();
    xbox.init_sortable_group_item_table();
    xbox.init_tooltip();

    xbox.load_oembeds();
    setTimeout(function () {
      xbox.load_icons_for_icon_selector();
    }, 200);

    $(document).on('click', '.xbox-save-btn', xbox.on_click_save_button);
    xbox.$xbox.on('click', '#xbox-reset', xbox.on_click_reset_values);
    xbox.$xbox.on('click', '#xbox-import', xbox.on_click_import_values);
    xbox.$xbox.on('ifClicked', '.xbox-type-import .xbox-radiochecks input', xbox.toggle_import);
    xbox.$xbox.on('click', '.xbox-type-import .xbox-radiochecks input, .xbox-wrap-import-inputs .item-key-from_url input, .xbox-wrap-import-inputs .item-key-from_file input', xbox.toggle_import);

    xbox.$xbox.on('click', '.xbox-add-group-item', xbox.new_group_item);
    xbox.$xbox.on('click', '.xbox-duplicate-group-item', xbox.new_group_item);
    xbox.$xbox.on('click', '.xbox-remove-group-item', xbox.maybe_remove_group_items);
    xbox.$xbox.on('click', '.xbox-group-control-item', xbox.on_click_group_control_item);
    xbox.$xbox.on('sort_group_items', '.xbox-group-wrap', xbox.sort_group_items);
    xbox.$xbox.on('sort_group_control_items', '.xbox-group-control', xbox.sort_group_control_items);

    xbox.$xbox.on('click', '.xbox-add-repeatable-item', xbox.add_repeatable_item);
    xbox.$xbox.on('click', '.xbox-remove-repeatable-item', xbox.remove_repeatable_item);
    xbox.$xbox.on('sort_repeatable_items', '.xbox-repeatable-wrap', xbox.sort_repeatable_items);

    xbox.$xbox.on('update_sortable_items', '.xbox-sortable-items', xbox.update_sortable_items);
    xbox.$xbox.on('after_sort_sortable_items', '.xbox-sortable-items', xbox.after_sort_sortable_items);
    xbox.$xbox.on('after_update_sortable_items', '.xbox-sortable-items', xbox.after_update_sortable_items);
    xbox.$xbox.on('click', '.xbox-item-sort-remove', xbox.remove_item_sortable_list);

    xbox.$xbox.on('click', '.xbox-upload-file, .xbox-preview-item .xbox-preview-handler', xbox.wp_media_upload);
    xbox.$xbox.on('click', '.xbox-remove-preview', xbox.remove_preview_item);
    xbox.$xbox.on('click', '.xbox-get-oembed', xbox.get_oembed);
    xbox.$xbox.on('click', '.xbox-get-image', xbox.get_image_from_url);
    xbox.$xbox.on('change', '.xbox-type-colorpicker input', xbox.on_change_input_colorpicker);
    xbox.$xbox.on('click', '.xbox-type-colorpicker .xbox-colorpicker-default-btn', xbox.set_default_value_colorpicker);
    xbox.$xbox.on('click', '.xbox-section.xbox-toggle-1 .xbox-section-header, .xbox-section .xbox-toggle-icon', xbox.toggle_section);
    xbox.$xbox.on('click', '.xbox-type-number .xbox-unit-has-picker-1', xbox.toggle_units_dropdown);
    xbox.$xbox.on('click', '.xbox-units-dropdown .xbox-unit-item', xbox.set_unit_number);
    xbox.$xbox.on('focus', '.xbox-type-text input.xbox-element', xbox.on_focus_input_type_text);
    xbox.$xbox.on('click', '.xbox-close-message', xbox.close_alert_message);

    xbox.refresh_active_main_tab();
    xbox.$xbox.on('click', '.xbox-main-tab .xbox-item-parent a', xbox.on_cick_item_main_tab);

    $(document).on('click', xbox.hide_units_dropdown);

    xbox.$xbox.on('focus', 'input.xbox-element', function (event) {
      $(this).closest('.xbox-field').removeClass('xbox-error');
    });

    xbox.sticky_submit_buttons();
    $(window).scroll(function () {
      xbox.sticky_submit_buttons();
    });
  };

  xbox.get_prefix = function($target){
    return $target.closest('.xbox').data('prefix');
  };

  xbox.on_cick_item_main_tab = function(e){
    var activeItem = $(this).attr('href').replace(/#/, '');
    var prefix = xbox.$xbox.data('prefix');
    localStorage.setItem('xbox-main-tab-item-active', activeItem.replace(prefix, '').replace('tab_item', 'tab-item'));
  };
  xbox.refresh_active_main_tab = function(){
    var activeItem = localStorage.getItem('xbox-main-tab-item-active');
    if( activeItem ){
      xbox.$xbox.find('.xbox-main-tab .xbox-item-parent.'+activeItem+' a').trigger('click');
    }
  };

  xbox.sticky_submit_buttons = function () {
    var $header = $('.xbox-header').first();
    var $actions = $header.find('.xbox-header-actions').first();
    var $my_account = $('#wp-admin-bar-my-account');
    if (!$actions.length || !$my_account.length || !$actions.data('sticky')) {
      return;
    }
    if ($(window).scrollTop() > $header.offset().top) {
      $my_account.css('padding-right', $actions.width() + 25);
      $actions.addClass('xbox-actions-sticky');
    } else {
      $my_account.css('padding-right', '');
      $actions.removeClass('xbox-actions-sticky');
    }
  };

  xbox.on_focus_input_type_text = function (event) {
    var $helper = $(this).next('.xbox-field-helper');
    if ($helper.length) {
      $(this).css('padding-right', ($helper.outerWidth() + 6) + 'px');
    }
  };

  xbox.hide_units_dropdown = function () {
    $('.xbox-units-dropdown').slideUp(200);
  };
  xbox.toggle_units_dropdown = function (event) {
    if ($(event.target).hasClass('xbox-spinner-handler') || $(event.target).hasClass('xbox-spinner-control')) {
      return;
    }
    event.stopPropagation();
    $(this).find('.xbox-units-dropdown').slideToggle(200);
  };
  xbox.set_unit_number = function (event) {
    var $btn = $(this);
    $btn.closest('.xbox-unit').find('input.xbox-unit-number').val($btn.data('value')).trigger('change');
    $btn.closest('.xbox-unit').find('span').text($btn.text());
  };

  xbox.load_icons_for_icon_selector = function (event) {
    var fields = [];
    $('.xbox-type-icon_selector').each(function (index, el) {
      var field_id = $(el).data('field-id');
      var options = $(el).find('.xbox-icons-wrap').data('options');
      if ($.inArray(field_id, fields) < 0 && options.load_with_ajax) {
        fields.push(field_id);
      }
    });

    $.each(fields, function (index, field_id) {
      xbox.load_icon_selector($('.xbox-field-id-' + field_id));
    });

    $(document).on('input', '.xbox-search-icon', function (event) {
      event.preventDefault();
      var value = $(this).val();
      var $container = $(this).closest('.xbox-field').find('.xbox-icons-wrap');
      xbox.filter_items(value, $container, '.xbox-item-icon-selector');
    });
    $(document).on('click', '.xbox-icon-actions .xbox-btn', function (event) {
      var value = $(this).data('search');
      var $container = $(this).closest('.xbox-field').find('.xbox-icons-wrap');
      xbox.filter_items(value, $container, '.xbox-item-icon-selector');
    });

    $(document).on('click', '.xbox-icons-wrap .xbox-item-icon-selector', function (event) {
      var $field = $(this).closest('.xbox-field');
      var $container = $field.find('.xbox-icons-wrap');
      var options = $container.data('options');
      $(this).addClass(options.active_class).siblings().removeClass(options.active_class);
      $field.find('input.xbox-element').val($(this).data('value')).trigger('change');
      $field.find('.xbox-icon-active').html($(this).html());
    });
  };

  xbox.filter_items = function (value, $container, selector) {
    $container.find(selector).each(function (index, item) {
      var data = $(item).data('key');
      if (is_empty(data)) {
        $(item).hide();
      } else {
        if (value == 'all' || data.indexOf(value) > -1) {
          $(item).show();
        } else {
          $(item).hide();
        }
      }
    });
  };

  xbox.load_icon_selector = function ($field) {
    var options = $field.find('.xbox-icons-wrap').data('options');
    $.ajax({
      type: 'post',
      dataType: 'json',
      url: XBOX_JS.ajax_url,
      data: {
        action: 'xbox_get_items',
        class_name: options.ajax_data.class_name,
        function_name: options.ajax_data.function_name,
        ajax_nonce: XBOX_JS.ajax_nonce
      },
      beforeSend: function () {
        $field.find('.xbox-icons-wrap').prepend("<i class='xbox-icon xbox-icon-spinner xbox-icon-spin xbox-loader'></i>");
      },
      success: function (response) {
        if (response) {
          if (response.success) {
            $.each(response.items, function (value, html) {
              var key = 'font ' + value;
              var type = 'icon font';
              if (key.indexOf('.svg') > -1) {
                key = key.split('/');
                key = key[key.length - 1];
                type = 'svg';
              }
              var $new_item = $('<div />', {
                'class': 'xbox-item-icon-selector',
                'data-value': value,
                'data-key': key,
                'data-type': type
              });
              $new_item.html(html);
              $field.find('.xbox-icons-wrap').append($new_item);
            });
            $field.find('.xbox-icons-wrap .xbox-item-icon-selector').css({
              'width': options.size,
              'height': options.size,
              'font-size': parseInt(options.size) - 14,
            });
            //c($field.first().find('.xbox-icons-wrap .xbox-item-icon-selector').length);//total icons
          }
        }
      },
      error: function (jqXHR, textStatus, errorThrown) {
      },
      complete: function (jqXHR, textStatus) {
        $field.find('.xbox-icons-wrap').find('.xbox-loader').remove();
      }
    });

    return '';
  };

  xbox.toggle_section = function (event) {
    event.stopPropagation();
    var $btn = $(this);
    var $section = $btn.closest('.xbox-section.xbox-toggle-1');
    var $section_body = $section.find('.xbox-section-body');
    var data_toggle = $section.data('toggle');
    var $icon = $section.find('.xbox-toggle-icon').first();
    if ($btn.hasClass('xbox-section-header') && data_toggle.target == 'icon') {
      return;
    }
    var object_toggle = {
      duration: parseInt(data_toggle.speed),
      complete: function () {
        if ($section_body.css('display') == 'block') {
          $icon.find('i').removeClass(data_toggle.close_icon).addClass(data_toggle.open_icon);
        } else {
          $icon.find('i').removeClass(data_toggle.open_icon).addClass(data_toggle.close_icon);
        }
      }
    };
    if (data_toggle.effect == 'slide') {
      $section_body.slideToggle(object_toggle);
    } else if (data_toggle.effect == 'fade') {
      $section_body.fadeToggle(object_toggle);
    }
    return false;
  };

  xbox.toggle_import = function (event) {
    var $input = $(this);
    var $wrap_input_file = $('.xbox-wrap-input-file');
    var $wrap_input_url = $('.xbox-wrap-input-url');
    var $wrap_textarea_json = $('.xbox-wrap-textarea-json');

    if ($input.next('img').length || ($input.val() != 'from_file' && $input.val() != 'from_url' && $input.val() != 'from_json') ) {
      $wrap_input_file.hide();
      $wrap_input_url.hide();
      $wrap_textarea_json.hide();
    }
    if ($input.val() == 'from_file') {
      $wrap_input_file.show();
      $wrap_input_url.hide();
      $wrap_textarea_json.hide();
    }
    if ($input.val() == 'from_url') {
      $wrap_input_file.hide();
      $wrap_input_url.show();
      $wrap_textarea_json.hide();
    }
    if ($input.val() == 'from_json') {
      $wrap_input_file.hide();
      $wrap_input_url.hide();
      $wrap_textarea_json.show();
    }
  };

  xbox.on_click_save_button = function (event) {
    //El botón que envía el formulario se cambió a "submit" para que valide los campos requeridos
    // var $btn = $(this);
    // var $xbox_form = xbox.get_form_element($btn);
    //
    // if( $xbox_form.length ){
    //   $xbox_form.submit();
    // } else {
    //   alert("Error: Xbox Form Not Found");
    // }
  };

  xbox.on_click_reset_values = function (event) {
    var $btn = $(this);
    var $xbox_form = xbox.get_form_element($btn);
    $.xboxConfirm({
      title: XBOX_JS.text.reset_popup.title,
      content: XBOX_JS.text.reset_popup.content,
      confirm_class: 'xbox-btn-blue',
      confirm_text: XBOX_JS.text.popup.accept_button,
      cancel_text: XBOX_JS.text.popup.cancel_button,
      onConfirm: function () {
        $xbox_form.prepend('<input type="hidden" name="' + $btn.attr('name') + '" value="true">');
        $xbox_form.submit();
      },
      onCancel: function () {
        return false;
      }
    });
    return false;
  };

  xbox.get_form_element = function ($btn) {
    var gutenbergEditor = !!$('body.block-editor-page').length;
    if( gutenbergEditor ){
      $xbox_form = $('.block-editor__container');//Gutenberg editor
    } else {
      var $xbox_form = $btn.closest('.xbox-form');//Admin pages
      if (!$xbox_form.length) {
        $xbox_form = $btn.closest('form#post');//Default wordpress editor
      }
    }
    return $xbox_form;
  };

  xbox.on_click_import_values = function (event) {
    var $btn = $(this);
    var gutenbergEditor = !!$('body.block-editor-page').length;
    var $xbox_form = xbox.get_form_element($btn);
    var importInput = '<input type="hidden" name="' + $btn.attr('name') + '" value="true">';
    $.xboxConfirm({
      title: XBOX_JS.text.import_popup.title,
      content: XBOX_JS.text.import_popup.content,
      confirm_class: 'xbox-btn-blue',
      confirm_text: XBOX_JS.text.popup.accept_button,
      cancel_text: XBOX_JS.text.popup.cancel_button,
      onConfirm: function () {
        if( gutenbergEditor ){
          $('form.metabox-location-normal').prepend(importInput);
          var $temp_button = $xbox_form.find('button.editor-post-publish-panel__toggle');
          var delay = 100;
          if( $temp_button.length ){
            $temp_button.trigger('click');
            delay = 900;
          }
          setTimeout(function(){
            var $publish_button = $xbox_form.find('button.editor-post-publish-button');
            if( $publish_button.length ){
              $publish_button.trigger('click');
              setTimeout(function(){
                location.reload();
              }, 6000);
            }
          }, delay);
        } else {
          $xbox_form.prepend(importInput);
          $xbox_form.prepend('<input type="hidden" name="xbox-import2" value="yes">');
          setTimeout(function(){
            if ($xbox_form.find('#publish').length) {
              $xbox_form.find('#publish').click();
            } else {
              $xbox_form.submit();
            }
          }, 800);
        }
      },
      onCancel: function () {
        return false;
      }
    });
    return false;
  };

  xbox.get_image_from_url = function (event) {
    var $btn = $(this);
    var $field = $btn.closest('.xbox-field');
    var $input = $field.find('.xbox-element-text');
    var $wrap_preview = $field.find('.xbox-wrap-preview');
    if (is_empty($input.val())) {
      $.xboxConfirm({
        title: XBOX_JS.text.validation_url_popup.title,
        content: XBOX_JS.text.validation_url_popup.content,
        confirm_text: XBOX_JS.text.popup.accept_button,
        hide_cancel: true
      });
      return false;
    }
    var image_class = $wrap_preview.data('image-class');
    var $new_item = $('<li />', { 'class': 'xbox-preview-item xbox-preview-image' });
    $new_item.html(
      '<img src="' + $input.val() + '" class="' + image_class + '">' +
      '<a class="xbox-btn xbox-btn-iconize xbox-btn-small xbox-btn-red xbox-remove-preview"><i class="xbox-icon xbox-icon-times-circle"></i></a>'
    );
    $wrap_preview.fadeOut(400, function () {
      $(this).html('').show();
    });
    $field.find('.xbox-get-image i').addClass('xbox-icon-spin');
    setTimeout(function () {
      $wrap_preview.html($new_item);
      $field.find('.xbox-get-image i').removeClass('xbox-icon-spin');
    }, 1200);
    return false;
  };

  xbox.load_oembeds = function (event) {
    $('.xbox-type-oembed').each(function (index, el) {
      if ($(el).find('.xbox-wrap-oembed').data('preview-onload')) {
        xbox.get_oembed($(el).find('.xbox-get-oembed'));
      }
    });
  };

  xbox.get_oembed = function (event) {
    var $btn;
    if ($(event.currentTarget).length) {
      $btn = $(event.currentTarget);
    } else {
      $btn = event;
    }
    var $field = $btn.closest('.xbox-field');
    var $input = $field.find('.xbox-element-text');
    var $wrap_preview = $field.find('.xbox-wrap-preview');
    if (is_empty($input.val()) && $(event.currentTarget).length) {
      $.xboxConfirm({
        title: XBOX_JS.text.validation_url_popup.title,
        content: XBOX_JS.text.validation_url_popup.content,
        confirm_text: XBOX_JS.text.popup.accept_button,
        hide_cancel: true
      });
      return false;
    }
    $.ajax({
      type: 'post',
      dataType: 'json',
      url: XBOX_JS.ajax_url,
      data: {
        action: 'xbox_get_oembed',
        oembed_url: $input.val(),
        preview_size: $wrap_preview.data('preview-size'),
        ajax_nonce: XBOX_JS.ajax_nonce
      },
      beforeSend: function () {
        $wrap_preview.fadeOut(400, function () {
          $(this).html('').show();
        });
        $field.find('.xbox-get-oembed i').addClass('xbox-icon-spin');
      },
      success: function (response) {
        if (response) {
          if (response.success) {
            var $new_item = $('<li />', { 'class': 'xbox-preview-item xbox-preview-oembed' });
            $new_item.html(
              '<div class="xbox-oembed xbox-oembed-provider-' + response.provider + ' xbox-element-oembed ">' +
              response.oembed +
              '<a class="xbox-btn xbox-btn-iconize xbox-btn-small xbox-btn-red xbox-remove-preview"><i class="xbox-icon xbox-icon-times-circle"></i></a>' +
              '</div>'
            );
            $wrap_preview.html($new_item);
          } else {
            $wrap_preview.html(response.message);
          }
        }
      },
      error: function (jqXHR, textStatus, errorThrown) {
      },
      complete: function (jqXHR, textStatus) {
        $field.find('.xbox-get-oembed i').removeClass('xbox-icon-spin');
      }
    });
    return false;
  };

  xbox.wp_media_upload = function (event) {
    if (wp === undefined) {
      return;
    }
    var $btn = $(this);
    var media = xbox.media;
    media.$field = $btn.closest('.xbox-field');
    media.field_id = media.$field.closest('.xbox-row').data('field-id');
    media.frame_id = media.$field.closest('.xbox').attr('id') + '_' + media.field_id;
    media.$upload_btn = media.$field.find('.xbox-upload-file');
    media.$wrap_preview = media.$field.find('.xbox-wrap-preview');
    media.multiple = media.$field.hasClass('xbox-has-multiple');
    media.$preview_item = undefined;
    media.attachment_id = undefined;

    if ($btn.closest('.xbox-preview-item').length) {
      media.$preview_item = $btn.closest('.xbox-preview-item');
    } else if (!media.multiple) {
      media.$preview_item = media.$field.find('.xbox-preview-item').first();
    }
    if (media.$preview_item) {
      media.attachment_id = media.$preview_item.find('.xbox-attachment-id').val();
    }

    if (media.frames[media.frame_id] !== undefined) {
      media.frames[media.frame_id].open();
      return;
    }

    media.frames[media.frame_id] = wp.media({
      title: media.$field.closest('.xbox-type-file').find('.xbox-element-label').first().text(),
      multiple: media.multiple ? 'add' : false,
    });
    media.frames[media.frame_id].on('open', xbox.on_open_wp_media).on('select', xbox.on_select_wp_media);
    media.frames[media.frame_id].open();
  };

  xbox.on_open_wp_media = function (event) {
    var media = xbox.media;
    var selected_files = xbox.media.frames[media.frame_id].state().get('selection');
    if (is_empty(media.attachment_id)) {
      return selected_files.reset();
    }
    var wp_attachment = wp.media.attachment(media.attachment_id);
    wp_attachment.fetch();
    selected_files.set(wp_attachment ? [wp_attachment] : []);
  };

  xbox.on_select_wp_media = function (event) {
    var media = xbox.media;
    var selected_files = media.frames[media.frame_id].state().get('selection').toJSON();
    var preview_size = media.$wrap_preview.data('preview-size');
    var attach_name = media.$wrap_preview.data('field-name');
    var control_img_id = media.$field.closest('.xbox-type-group').find('.xbox-group-control').data('image-field-id');

    media.$field.trigger('xbox_before_add_files', [selected_files, xbox.media]);
    $(selected_files).each(function (index, obj) {
      var image = '';
      var inputs = '';
      var item_body = '';
      var $new_item = $('<li />', { 'class': 'xbox-preview-item xbox-preview-file' });

      if (obj.type == 'image') {
        $new_item.addClass('xbox-preview-image');
        item_body = '<img src="' + obj.url + '" style="width: ' + preview_size.width + '; height: ' + preview_size.height + '" data-full-img="' + obj.url + '" class="xbox-image xbox-preview-handler">';
      } else if (obj.type == 'video') {
        $new_item.addClass('xbox-preview-video');
        item_body = '<div class="xbox-video">';
        item_body += '<video controls style="width: ' + preview_size.width + '; height: ' + preview_size.height + '"><source src="' + obj.url + '" type="' + obj.mime + '"></video>';
        item_body += '</div>';
      } else {
        item_body = '<img src="' + obj.icon + '" class="xbox-preview-icon-file xbox-preview-handler"><a href="' + obj.url + '" class="xbox-preview-download-link">' + obj.filename + '</a><span class="xbox-preview-mime xbox-preview-handler">' + obj.mime + '</span>';
      }

      if (media.multiple) {
        inputs = '<input type="hidden" name="' + media.$upload_btn.data('field-name') + '" value="' + obj.url + '" class="xbox-element xbox-element-hidden">';
      }
      inputs += '<input type="hidden" name="' + attach_name + '" value="' + obj.id + '" class="xbox-attachment-id">';

      $new_item.html(inputs + item_body + '<a class="xbox-btn xbox-btn-iconize xbox-btn-small xbox-btn-red xbox-remove-preview"><i class="xbox-icon xbox-icon-times-circle"></i></a>');

      if (media.multiple) {
        if (media.$preview_item) {
          //Sólo agregamos los nuevos
          if (media.attachment_id != obj.id) {
            media.$preview_item.after($new_item);
          }
        } else {
          media.$wrap_preview.append($new_item);
        }
      } else {
        media.$wrap_preview.html($new_item);
        media.$field.find('.xbox-element').attr('value', obj.url);
        if (obj.type == 'image') {
          //Sincronizar con la imagen de control de un grupo
          if (media.field_id == control_img_id) {
            xbox.synchronize_selector_preview_image('.xbox-control-image', media.$wrap_preview, 'add', obj.url);
          }
          //Sincronizar con otros elementos
          xbox.synchronize_selector_preview_image('', media.$wrap_preview, 'add', obj.url);
        }
      }
    });
    media.$field.trigger('xbox_after_add_files', [selected_files, media]);
  };

  xbox.remove_preview_item = function (event) {
    var $btn = $(this);
    var $field = $btn.closest('.xbox-field');
    var field_id = $field.closest('.xbox-row').data('field-id');
    var control_data_img = $field.closest('.xbox-type-group').find('.xbox-group-control').data('image-field-id');
    var $wrap_preview = $field.find('.xbox-wrap-preview');
    var multiple = $field.hasClass('xbox-has-multiple');

    $field.trigger('xbox_before_remove_preview_item', [multiple]);

    if (!multiple) {
      $field.find('.xbox-element').attr('value', '');
    }
    $btn.closest('.xbox-preview-item').remove();

    if (!multiple && $btn.closest('.xbox-preview-item').hasClass('xbox-preview-image')) {
      if (field_id == control_data_img) {
        xbox.synchronize_selector_preview_image('.xbox-control-image', $wrap_preview, 'remove', '');
      }
      xbox.synchronize_selector_preview_image('', $wrap_preview, 'remove', '');
    }
    $field.find('.xbox-element').trigger('change');
    $field.trigger('xbox_after_remove_preview_item', [multiple]);
    return false;
  };

  xbox.synchronize_selector_preview_image = function (selectors, $wrap_preview, action, value) {
    selectors = selectors || $wrap_preview.data('synchronize-selector');
    if (!is_empty(selectors)) {
      selectors = selectors.split(',');
      $.each(selectors, function (index, selector) {
        var $element = $(selector);
        if ($element.closest('.xbox-type-group').length) {
          if ($element.closest('.xbox-group-control').length) {
            $element = $element.closest('.xbox-group-control-item.xbox-active').find(selector);
          } else {
            $element = $element.closest('.xbox-group-item.xbox-active').find(selector);
          }
        }
        if ($element.is('img')) {
          $element.fadeOut(300, function () {
            if ($element.closest('.xbox-group-control').length) {
              $element.attr('src', value);
            } else {
              $element.attr('src', value);
            }
          });
        } else {
          $element.fadeOut(300, function () {
            if ($element.closest('.xbox-group-control').length) {
              $element.css('background-image', 'url(' + value + ')');
            } else {
              $element.css('background-image', 'url(' + value + ')');
            }
          });
        }
        if (action == 'add') {
          $element.fadeIn(300);
        }
        var $input = $element.closest('.xbox-field').find('input.xbox-element');
        if ($input.length) {
          $input.attr('value', value);
        }

        var $close_btn = $element.closest('.xbox-preview-item').find('.xbox-remove-preview');
        if ($close_btn.length) {
          if (action == 'add' && $input.is(':visible')) {
            $close_btn.show();
          }
          if (action == 'remove') {
            $close_btn.hide();
          }
        }
      });
    }
  };

  xbox.reinit_js_plugins = function ($new_element) {
    //Inicializar Tabs
    $new_element.find('.xbox-tab').each(function (iterator, item) {
      xbox.init_tab($(item));
    });

    //Inicializar Switcher
    $new_element.find('.xbox-type-switcher input.xbox-element').each(function (iterator, item) {
      $(item).xboxSwitcher('destroy');
      xbox.init_switcher($(item));
    });

    //Inicializar Spinner
    $new_element.find('.xbox-type-number .xbox-field.xbox-has-spinner').each(function (iterator, item) {
      xbox.init_spinner($(item));
    });

    //Inicializar radio buttons y checkboxes
    $new_element.find('.xbox-has-icheck .xbox-radiochecks.init-icheck').each(function (iterator, item) {
      xbox.destroy_icheck($(item));
      xbox.init_checkbox($(item));
    });

    //Inicializar Colorpicker
    $new_element.find('.xbox-colorpicker-color').each(function (iterator, item) {
      xbox.init_colorpicker($(item));
    });

    //Inicializar Dropdown
    $new_element.find('.ui.selection.dropdown').each(function (iterator, item) {
      xbox.init_dropdown($(item));
    });

    //Inicializar Sortables de grupos
    $new_element.find('.xbox-group-control.xbox-sortable').each(function (iterator, item) {
      xbox.init_sortable_group_items($(item));
    });

    //Inicializar Sortable de items repetibles
    $new_element.find('.xbox-repeatable-wrap.xbox-sortable').each(function (iterator, item) {
      xbox.init_sortable_repeatable_items($(item));
    });

    //Inicializar Sortable de preview items
    $new_element.find('.xbox-wrap-preview-multiple').each(function (iterator, item) {
      xbox.init_sortable_preview_items($(item));
    });

    //Inicializar Ace editor
    $new_element.find('.xbox-code-editor').each(function (iterator, item) {
      xbox.destroy_ace_editor($(item));
      xbox.init_code_editor($(item));
    });

    //Inicializar Tooltip
    xbox.init_tooltip($new_element.find('.xbox-tooltip-handler'));
  };


  xbox.destroy_wp_editor = function ($selector) {
    if (typeof tinyMCEPreInit === 'undefined' || typeof tinymce === 'undefined' || typeof QTags == 'undefined') {
      return;
    }

    //Destroy editor
    $selector.find('.quicktags-toolbar, .mce-tinymce.mce-container').remove();
    tinymce.execCommand('mceRemoveEditor', true, $selector.find('.wp-editor-area').attr('id'));

    //Register editor to init
    $selector.addClass('init-wp-editor');
  };

  xbox.on_init_wp_editor = function (wp_editor, args) {
    $('.xbox').trigger('xbox_on_init_wp_editor', wp_editor, args);
  };

  xbox.on_setup_wp_editor = function (wp_editor) {
    $('.xbox').trigger('xbox_on_setup_wp_editor', wp_editor);
    if (typeof tinymce === 'undefined') {
      return;
    }
    var $textarea = $(wp_editor.settings.selector);
    wp_editor.on('change mouseleave input', function (e) {
      if( wp_editor ){
        var value = wp_editor.getContent();
        $textarea.text(value).val(value);
      }
    });
  };

  xbox.init_wp_editor = function ($selector) {
    if (typeof tinyMCEPreInit === 'undefined' || typeof tinymce === 'undefined' || typeof QTags == 'undefined') {
      return;
    }
    $selector.removeClass('init-wp-editor');
    $selector.removeClass('html-active').addClass('tmce-active');
    var $textarea = $selector.find('.wp-editor-area');
    var ed_id = $textarea.attr('id');
    var old_ed_id = $selector.closest('.xbox-group-wrap').find('.xbox-group-item').eq(0).find('.wp-editor-area').first().attr('id');

    $textarea.show();

    var ed_settings = jQuery.extend(tinyMCEPreInit.mceInit[old_ed_id], {
      body_class: ed_id,
      selector: '#' + ed_id,
      skin: "lightgray",
      entities: "38,amp,60,lt,62,gt",
      entity_encoding: "raw",
      preview_styles: "font-family font-size font-weight font-style text-decoration text-transform",
      relative_urls: false,
      remove_script_host: false,
      resize: "vertical",
      plugins: "charmap,colorpicker,hr,lists,media,paste,tabfocus,textcolor,fullscreen,wordpress,wpautoresize,wpeditimage,wpemoji,wpgallery,wplink,wpdialogs,wptextpattern,wpview,directionality,image",
      tabfocus_elements: ":prev,:next",
      theme: "modern",
      fix_list_elements: true,
      mode: "tmce",//tmce,exact
      menubar : false,
      toolbar1: "formatselect,bold,italic,bullist,numlist,blockquote,alignleft,aligncenter,alignright,link,wp_more,spellchecker,fullscreen,wp_adv",
      toolbar2: "strikethrough,hr,forecolor,pastetext,removeformat,charmap,outdent,indent,undo,redo,rtl,ltr,wp_help",
      toolbar3: "",
      toolbar4: "",
      wpautop: true,
      setup: function(wp_editor) {
        xbox.on_setup_wp_editor(wp_editor);//php class-field.php set_args();
        wp_editor.on('init', function(args) {
          xbox.on_init_wp_editor(wp_editor, args);
        });
      }
    });

    tinyMCEPreInit.mceInit[ed_id] = ed_settings;

    // Initialize wp_editor tinymce instance
    tinymce.init(tinyMCEPreInit.mceInit[ed_id]);
    //tinymce.execCommand( 'mceAddEditor', true, ed_id );

    //Quick tags Settings
    var qt_settings = jQuery.extend({}, tinyMCEPreInit.qtInit[old_ed_id]);
    qt_settings.id = ed_id;
    new QTags(ed_id);
    QTags._buttonsInit();
  };

  xbox.init_switcher = function ($selector) {
    $selector = is_empty($selector) ? $('.xbox-type-switcher input.xbox-element') : $selector;
    $selector.xboxSwitcher();
  };

  xbox.init_spinner = function ($selector) {
    $selector = is_empty($selector) ? $('.xbox-type-number .xbox-field.xbox-has-spinner') : $selector;
    $selector.spinnerNum('delay', 300);
    $selector.spinnerNum('changing', function (e, newVal, oldVal) {
      $(this).trigger('xbox_changed_value', newVal);
    });
  };

  xbox.init_tab = function ($selector) {
    $selector = is_empty($selector) ? $('.xbox-tab') : $selector;
    $selector.each(function(index, el){
      var $tab = $(el);
      if( $tab.closest('.xbox-source-item').length ){
        return;//continue each
      }
      $tab.find('.xbox-tab-nav .xbox-item').removeClass('active');
      $tab.find('.xbox-accordion-title').remove();

      var type_tab = 'responsive';
      if ($tab.closest('#side-sortables').length) {
        type_tab = 'accordion';
      }
      $tab.xboxTabs({
        collapsible: true,
        type: type_tab
      });
    });
  };

  xbox.init_tooltip = function ($selector) {
    $selector = is_empty($selector) ? $('.xbox-tooltip-handler') : $selector;
    $selector.each(function (index, el) {
      var title_content = '';
      var title_tooltip = $(el).data('tipso-title');
      var position = $(el).data('tipso-position') ? $(el).data('tipso-position') : 'top';
      if (!is_empty(title_tooltip)) {
        title_content = '<h3>' + title_tooltip + '</h3>';
      }
      $(el).tipso({
        delay: 10,
        speed: 100,
        offsetY: 2,
        tooltipHover: true,
        position: position,
        titleContent: title_content,
        onBeforeShow: function ($element, element, e) {
          $(e.tipso_bubble).addClass($(el).closest('.xbox').data('skin'));
        },
        onShow: function ($element, element, e) {
          //$(e.tipso_bubble).removeClass('top').addClass(position);
        },
        //hideDelay: 1000000
      });
    });
  };

  xbox.init_checkbox = function ($selector) {
    $selector = is_empty($selector) ? $('.xbox-has-icheck .xbox-radiochecks.init-icheck') : $selector;
    $selector.find('input').iCheck({
      radioClass: 'iradio_flat-blue',
      checkboxClass: 'icheckbox_flat-blue',
    });
  };

  xbox.destroy_icheck = function ($selector) {
    $selector.find('input').each(function (index, input) {
      $(input).attr('style', '');
      $(input).next('ins').remove();
      $(input).unwrap();
    });
  };

  xbox.init_image_selector = function ($selector) {
    $selector = is_empty($selector) ? $('.xbox-type-image_selector .init-image-selector, .xbox-type-import .init-image-selector') : $selector;
    $selector.xboxImageSelector({
      active_class: 'xbox-active'
    });
  };

  xbox.init_dropdown = function ($selector) {
    $selector = is_empty($selector) ? $('.ui.selection.dropdown') : $selector;
    $selector.each(function (index, el) {
      var max_selections = parseInt($(el).data('max-selections'));
      var value = $(el).find('input[type="hidden"]').val();
      if (max_selections > 1 && $(el).hasClass('multiple')) {
        $(el).dropdownXbox({
          maxSelections: max_selections,
          fullTextSearch: true,
          onChange: function(value, text, $choice){
            $(el).trigger('xbox_dropdown_changed_value', [value, text, $choice] );
          },
          onAdd: function(addedValue, addedText, $addedChoice){
            $(el).trigger('xbox_dropdown_added_item', [addedValue, addedText, $addedChoice] );
          },
          onRemove: function(removedValue, removedText, $removedChoice){
            $(el).trigger('xbox_dropdown_removed_item', [removedValue, removedText, $removedChoice] );
          }
        });
        $(el).dropdownXbox('set selected', value.split(','));

        if( $(el).hasClass('xbox-sortable-values') ){
          $(el).sortable({
            items: '.ui.label',
            placeholder: "xbox-sortable-placeholder",
            start: function (event, ui) {
              ui.placeholder.css({
                'width': ui.item.css('width'),
                'height': ui.item.css('height'),
                'margin': ui.item.css('margin'),
                'vertical-align': ui.item.css('vertical-align'),
                'white-space': ui.item.css('white-space'),
              });
            },
            update: function (event, ui) {
              var val = [];
              $(event.target).find('.ui.label').each(function(i, item){
                val.push($(item).data('value'));
              });
              $(event.target).find('input').val(val.join(',')).trigger('change');
            }
          }).disableSelection();
        }

        if( $(el).hasClass('xbox-select-sortable') ){
          xbox.init_sortable_select_sortable_items( $(el) );
          xbox.on_change_fields_select_sortable( $(el) );
        }

      } else {
        $(el).dropdownXbox({
          fullTextSearch: true,
        });
      }
    });
  };

  xbox.set_default_value_colorpicker = function () {
    var $field = $(this).closest('.xbox-field');
    var value = $field.data('default');
    if (value) {
      xbox.reset_colorpicker($field, value);
      $field.find('input.xbox-element').attr('value', value).val(value);
    }
  };

  xbox.on_change_input_colorpicker = function () {
    var $field = $(this).closest('.xbox-field');
    var value = $(this).val();
    xbox.reset_colorpicker($field, value);
  };

  xbox.reset_colorpicker = function ($field, value) {
    $field.find('.xbox-colorpicker-color').remove();
    $field.find('.xbox-colorpicker-preview').append('<span class="xbox-colorpicker-color">');
    $field.find('.xbox-colorpicker-color').attr('value', value).css('background-color', value);
    xbox.init_colorpicker($field.find('.xbox-colorpicker-color'));
  };

  xbox.init_colorpicker = function ($selector) {
    $selector = is_empty($selector) ? $('.xbox-colorpicker-color') : $selector;
    $selector.colorPicker({
      cssAddon: '.cp-color-picker {margin-top:6px;}',
      buildCallback: function ($elm) {
      },
      renderCallback: function ($elm, toggled) {
        var $field = $elm.closest('.xbox-field');
        this.$UI.find('.cp-alpha').toggle($field.hasClass('xbox-has-alpha'));
        var value = this.color.toString('rgb', true);
        if (!$field.hasClass('xbox-has-alpha')) {//|| value.endsWith(', 1)')
          value = '#' + this.color.colors.HEX;
        }
        value = value.indexOf('NAN') > -1 ? '' : value;
        $field.find('input').attr('value', value).val(value);
        $field.find('.xbox-colorpicker-color').attr('value', value).css('background-color', value);

        //Para la gestión de eventos
        $field.find('input').trigger('input');
      }
    });
  };

  xbox.destroy_ace_editor = function ($selector) {
    var $textarea = $selector.closest('.xbox-field').find('textarea.xbox-element');
    $selector.text($textarea.val());
  };

  xbox.init_code_editor = function ($selector) {
    $selector = is_empty($selector) ? $('.xbox-code-editor') : $selector;
    $selector.each(function (index, el) {
      var editor = ace.edit($(el).attr('id'));
      var language = $(el).data('language');
      var theme = $(el).data('theme');
      editor.setTheme("ace/theme/" + theme);
      editor.getSession().setMode("ace/mode/" + language);
      editor.setFontSize(15);
      editor.setShowPrintMargin(false);
      editor.getSession().on('change', function (e) {
        $(el).closest('.xbox-field').find('textarea.xbox-element').text(editor.getValue());
      });

      //Include auto complete
      ace.config.loadModule('ace/ext/language_tools', function () {
        editor.setOptions({
          enableBasicAutocompletion: true,
          enableSnippets: true
        });
      });
    });
  };

  xbox.init_sortable_preview_items = function ($selector) {
    $selector = is_empty($selector) ? $('.xbox-wrap-preview-multiple') : $selector;
    $selector.sortable({
      items: '.xbox-preview-item',
      placeholder: "xbox-preview-item xbox-sortable-placeholder",
      start: function (event, ui) {
        ui.placeholder.css({
          'width': ui.item.css('width'),
          'height': ui.item.css('height'),
        });
      },
    }).disableSelection();
  };

  xbox.init_sortable_checkbox = function ($selector) {
    $selector = is_empty($selector) ? $('.xbox-has-icheck .xbox-radiochecks.init-icheck.xbox-sortable') : $selector;
    $selector.sortable({
      items: '>label',
      placeholder: "xbox-icheck-sortable-item xbox-sortable-placeholder",
      start: function (event, ui) {
        ui.placeholder.css({
          'width': ui.item.css('width'),
          'height': ui.item.css('height'),
        });
      },
    }).disableSelection();
  };

  xbox.init_sortable_repeatable_items = function ($selector) {
    $selector = is_empty($selector) ? $('.xbox-repeatable-wrap.xbox-sortable') : $selector;
    $selector.sortable({
      handle: '.xbox-sort-item',
      items: '.xbox-repeatable-item',
      placeholder: "xbox-repeatable-item xbox-sortable-placeholder",
      start: function (event, ui) {
        ui.placeholder.css({
          'width': ui.item.css('width'),
          'height': ui.item.css('height'),
        });
      },
      update: function (event, ui) {
        // No funciona bien con wp_editor, mejor usamos 'stop'
        // var $repeatable_wrap = $(event.target);
        // $repeatable_wrap.trigger('sort_repeatable_items');
      },
      stop: function (event, ui) {
        var $repeatable_wrap = $(event.target);
        $repeatable_wrap.trigger('sort_repeatable_items');
      }
    }).disableSelection();
  };

  xbox.init_sortable_group_items = function ($selector) {
    $selector = is_empty($selector) ? $('.xbox-group-control.xbox-sortable') : $selector;
    $selector.sortable({
      items: '.xbox-group-control-item',
      placeholder: "xbox-sortable-placeholder",
      start: function (event, ui) {
        ui.placeholder.css({
          'width': ui.item.css('width'),
          'height': ui.item.css('height'),
        });
      },
      update: function (event, ui) {
        var $group_control = $(event.target);
        var $group_wrap = $group_control.next('.xbox-group-wrap');

        var old_index = parseInt(ui.item.attr('data-index'));
        var new_index = $group_control.find('.xbox-group-control-item').index(ui.item);
        var $group_item = $group_wrap.children('.xbox-group-item[data-index=' + old_index + ']');
        var $group_item_reference = $group_wrap.children('.xbox-group-item[data-index=' + new_index + ']');
        var start_index = 0;
        var end_index;

        if (old_index < new_index) {
          $group_item.insertAfter($group_item_reference);
          start_index = old_index;
          end_index = new_index;
        } else {
          $group_item.insertBefore($group_item_reference);
          start_index = new_index;
          end_index = old_index;
        }

        $group_wrap.trigger('xbox_on_sortable_group_item', [old_index, new_index]);

        $group_control.trigger('sort_group_control_items');

        $group_wrap.trigger('sort_group_items', [start_index, end_index]);

        //Click event, to initialize some fields -> (WP Editors)
        if (ui.item.hasClass('xbox-active')) {
          ui.item.trigger('click');
        }
      }
    }).disableSelection();
  };

  xbox.init_sortable_group_item_table = function ($selector) {
    $selector = is_empty($selector) ? $('.xbox-group-table-layout.xbox-sortable') : $selector;
    $selector.sortable({
      items: '.xbox-group-item',
      handle: '.xbox-icon-sort',
      placeholder: "xbox-sortable-placeholder",
      start: function (event, ui) {
      },
      update: function (event, ui) {
        var $target = $(event.target);
        var $group_wrap = $target.find('.xbox-group-wrap');

        var old_index = parseInt(ui.item.attr('data-index'));
        var new_index = $target.find('.xbox-group-item').index(ui.item);
        var $group_item = $group_wrap.children('.xbox-group-item[data-index=' + old_index + ']');
        var $group_item_reference = $group_wrap.children('.xbox-group-item[data-index=' + new_index + ']');
        var start_index = 0;
        var end_index;

        if (old_index < new_index) {
          $group_item.insertAfter($group_item_reference);
          start_index = old_index;
          end_index = new_index;
        } else {
          $group_item.insertBefore($group_item_reference);
          start_index = new_index;
          end_index = old_index;
        }

        $group_wrap.trigger('xbox_on_sortable_group_item', [old_index, new_index]);

        $group_wrap.trigger('sort_group_items', [start_index, end_index]);

        //Click event, to initialize some fields -> (WP Editors)
        if (ui.item.hasClass('xbox-active')) {
          ui.item.trigger('click');
        }
      }
    }).disableSelection();
  };

  xbox.init_sortable_select_sortable_items = function ($select_sortable) {
    var fields = xbox.get_select_sortable_fields($select_sortable);
    fields.$sortableList.sortable({
      items: '.xbox-item-sort',
      placeholder: "xbox-sortable-placeholder",
      start: function (event, ui) {
        ui.placeholder.css({
          'width': ui.item.css('width'),
          'height': ui.item.css('height'),
        });
      },
      update: function (event, ui) {
        $(event.target).trigger('update_sortable_items');
        $(event.target).trigger('after_sort_sortable_items');
      }
    }).disableSelection();
  };

  xbox.add_repeatable_item = function (event) {
    var $btn = $(this);
    var $repeatable_wrap = $btn.closest('.xbox-repeatable-wrap');
    $repeatable_wrap.trigger('xbox_before_add_repeatable_item');

    var $source_item = $btn.prev('.xbox-repeatable-item');
    var index = parseInt($source_item.data('index'));
    var $cloned = $source_item.clone();
    var $new_item = $('<div />', { 'class': $cloned.attr('class'), 'data-index': index + 1, 'style': 'display: none' });

    xbox.set_changed_values($cloned, $repeatable_wrap.closest('.xbox-row').data('field-type'));

    $new_item.html($cloned.html());
    $source_item.after($new_item);
    $new_item.slideDown(150, function () {
      //Ordenar y cambiar ids y names
      $repeatable_wrap.trigger('sort_repeatable_items');
      //Actualizar eventos
      xbox.reinit_js_plugins($new_item);
    });
    $repeatable_wrap.trigger('xbox_after_add_repeatable_item');
    return false;
  };

  xbox.remove_repeatable_item = function (event) {
    var $repeatable_wrap = $(this).closest('.xbox-repeatable-wrap');
    if ($repeatable_wrap.find('.xbox-repeatable-item').length > 1) {
      $repeatable_wrap.trigger('xbox_before_remove_repeatable_item');
      var $item = $(this).closest('.xbox-repeatable-item');
      $item.slideUp(150, function () {
        $item.remove();
        $repeatable_wrap.trigger('sort_repeatable_items');
        $repeatable_wrap.trigger('xbox_after_remove_repeatable_item');
      });
    }
    return false;
  };

  xbox.sort_repeatable_items = function (event) {
    var $repeatable_wrap = $(event.target);
    var row_level = parseInt($repeatable_wrap.closest('[class*="xbox-row"]').data('row-level'));

    $repeatable_wrap.find('.xbox-repeatable-item').each(function (index, item) {
      xbox.update_attributes($(item), index, row_level);

      //Destroy WP Editors
      $(item).find('.wp-editor-wrap').each(function (index, el) {
        xbox.destroy_wp_editor($(el));
      });
      xbox.update_fields_on_item_active($(item));
    });
  };

  xbox.new_group_item = function (event) {
    if ($(event.currentTarget).hasClass('xbox-duplicate-group-item')) {
      xbox.duplicate = true;
      event.stopPropagation();
    } else {
      xbox.duplicate = false;
    }
    var $group = $(this).closest('.xbox-type-group');
    var $control_item = xbox.add_group_control_item(event, $(this));
    var $group_item = xbox.add_group_item(event, $(this));

    var args = {
      event: event,
      $btn: $(this),
      $group: $group,
      duplicate: xbox.duplicate,
      $group_item: $group_item,
      $control_item: $control_item,
      index: $group_item.data('index'),
      type: $group_item.data('type')
    };

    $group.trigger('xbox_after_add_group_item', [args]);

    //Active new item
    $control_item.trigger('click');

    return false;
  };

  xbox.get_group_control = function ($target) {
    return $target.closest('.xbox-type-group').find('.xbox-group-control').first();
  };

  xbox.get_control_item = function ($group_control, index) {
    return $group_control.children('.xbox-group-control-item').eq(index);
  };

  xbox.get_group_item = function ($group_wrap, index) {
    return $group_wrap.children('.xbox-group-item').eq(index);
  };

  xbox.get_group_item_type = function ($group_item) {
    return $group_item.find('.xbox-input-group-item-type').val();
  };

  xbox.get_group_item_visibility = function ($group_item) {
    return $group_item.find('.xbox-input-group-item-visibility').val();
  };

  xbox.add_group_control_item = function (event, $btn) {
    var item_type = $btn.data('item-type');
    var $group = $btn.closest('.xbox-type-group');
    var $group_wrap = $group.find('.xbox-group-wrap').first();
    var $group_control = xbox.get_group_control($btn);
    var $last_control_item = $group_control.find('.xbox-group-control-item').last();
    var index = -1;
    if ($last_control_item.length) {
      index = $last_control_item.data('index');
    }
    var $source_item = $group_wrap.closest('.xbox-content').find('>.xbox-source-item').find('.xbox-group-control-item');

    if (xbox.duplicate) {
      if( xbox.is_group_table_layout( $btn ) ){
        index = $btn.closest('.xbox-group-item').data('index');
      } else {
        index = $btn.closest('.xbox-group-control-item').index();
      }
      $source_item = xbox.get_control_item($group_control, index);
      var $group_item = xbox.get_group_item($group_wrap, index);
      item_type = xbox.get_group_item_type($group_item);
    }
    index = parseInt(index);

    var args = {
      event: event,
      $btn: $btn,
      $group: $group,
      duplicate: xbox.duplicate,
      $group_item: xbox.get_group_item($group_wrap, index),
      $control_item: $source_item,
      index: index,
      type: item_type
    };
    $group.trigger('xbox_before_add_group_item', [args]);
    
    var $cloned = $source_item.clone();
    var $new_item = $('<li />', { 'class': $cloned.attr('class'), 'data-index': index + 1, 'data-type': item_type });

    $new_item.html($cloned.html());
    $source_item.after($new_item);

    //Add new item
    if (index == -1) {
      $group_control.append($new_item);
    } else {
      xbox.get_control_item($group_control, index).after($new_item);
    }
    $new_item = $group_control.children('.xbox-group-control-item').eq(index + 1);

    $new_item.alterClass('control-item-type-*', 'control-item-type-' + item_type);
    //$new_item.find('input.xbox-input-group-item-type').val(item_type);
    $group_control.trigger('sort_group_control_items');

    if (xbox.duplicate === false && $new_item.find('.xbox-control-image').length) {
      $new_item.find('.xbox-control-image').css('background-image', 'url()');
    }
    if (xbox.duplicate === false) {
      var $input = $new_item.find('.xbox-inner input');
      if ($input.length) {
        var value = $group_control.data('control-name').toString();
        $input.attr('value', value.replace(/(#\d?)/g, '#' + (index + 2)));
        $input.val(value.replace(/(#\d?)/g, '#' + (index + 2)));
        if ($btn.hasClass('xbox-custom-add')) {
          $input.attr('value', $btn.text()).val($btn.text());
        }
      }
    }
    return $new_item;
  };

  xbox.add_group_item = function (event, $btn) {
    var item_type = $btn.data('item-type');
    var $group_wrap = $btn.closest('.xbox-type-group').find('.xbox-group-wrap').first();
    var $last_group_item = $group_wrap.children('.xbox-group-item').last();
    var index = -1;
    if ($last_group_item.length) {
      index = $last_group_item.data('index');
    }
    var $source_item = $group_wrap.closest('.xbox-content').find('>.xbox-source-item').find('.xbox-group-item');

    if (xbox.duplicate) {
      if( xbox.is_group_table_layout( $btn ) ){
        index = $btn.closest('.xbox-group-item').data('index');
      } else {
        index = $btn.closest('.xbox-group-control-item').index();
      }
      $source_item = xbox.get_group_item($group_wrap, index);
      item_type = xbox.get_group_item_type($source_item);
    }

    index = parseInt(index);
    var row_level = parseInt($source_item.closest('.xbox-row').data('row-level'));
    var $cloned = $source_item.clone();
    var $cooked_item = xbox.cook_group_item($cloned, row_level, index);
    var $new_item = $('<div />', { 'class': $cloned.attr('class'), 'data-index': index + 1, 'data-type': item_type });
    $new_item.html($cooked_item.html());
    //Add new item
    if (index == -1) {
      $group_wrap.append($new_item);
    } else {
      xbox.get_group_item($group_wrap, index).after($new_item);
    }
    $new_item = $group_wrap.children('.xbox-group-item').eq(index + 1);
    $new_item.alterClass('group-item-type-*', 'group-item-type-' + item_type);
    $new_item.find('input.xbox-input-group-item-type').val(item_type);
    $group_wrap.trigger('sort_group_items', [index + 1]);

    //Actualizar eventos
    xbox.reinit_js_plugins($new_item);

    if (xbox.duplicate === false) {
      //xbox.set_default_values( $new_item );//Ya no es necesario por el nuevo source item
    }
    return $new_item;
  };

  xbox.cook_group_item = function ($group_item, row_level, prev_index) {
    var index = prev_index + 1;

    if (xbox.duplicate) {
      xbox.set_changed_values($group_item);
    } else {
      //No es duplicado, restaurar todo, eliminar items de grupos internos
      $group_item.find('.xbox-group-wrap').each(function (index, wrap_group) {
        $(wrap_group).find('.xbox-group-item').first().addClass('xbox-active').siblings().remove();
        $(wrap_group).prev('.xbox-group-control').children('.xbox-group-control-item').first().addClass('xbox-active').siblings().remove();
      });
      $group_item.find('.xbox-repeatable-wrap').each(function (index, wrap_repeat) {
        $(wrap_repeat).find('.xbox-repeatable-item').not(':first').remove();
      });
    }

    xbox.update_attributes($group_item, index, row_level);

    return $group_item;
  };

  xbox.set_changed_values = function ($new_item, field_type) {
    var $textarea, $input;
    $new_item.find('.xbox-field').each(function (iterator, item) {
      var type = field_type || $(item).closest('.xbox-row').data('field-type');
      switch (type) {
        case 'text':
        case 'number':
        case 'oembed':
        case 'file':
        case 'image':
          $input = $(item).find('input.xbox-element');
          $input.attr('value', $input.val());
          break;
      }
    });
  };

  xbox.maybe_remove_group_items = function (eventOrItems) {
    var $btn;
    if( eventOrItems && eventOrItems.target ){
      event.preventDefault();
      event.stopPropagation();
      $btn = $(this);
    }
    $.xboxConfirm({
      title: XBOX_JS.text.remove_item_popup.title,
      content: XBOX_JS.text.remove_item_popup.content,
      confirm_class: 'xbox-btn-blue',
      confirm_text: XBOX_JS.text.popup.accept_button,
      cancel_text: XBOX_JS.text.popup.cancel_button,
      onConfirm: function () {
        if( $btn != undefined ){
          setTimeout(function () {
            xbox.remove_group_item($btn, true);
          }, xbox.delays.removeItem.confirm);
        } else {
          xbox.remove_group_items(eventOrItems);
        }
      }
    });
    return false;
  };

  xbox.remove_group_item = function ($btn, sort_items) {
    var $row = $btn.closest('.xbox-type-group');
    var $group_wrap = $row.find('.xbox-group-wrap').first();
    var $group_control = xbox.get_group_control($btn);
    var index = -1;
    if( xbox.is_group_table_layout( $btn ) ){
      index = $btn.closest('.xbox-group-item').data('index');
    } else {
      index = $btn.closest('.xbox-group-control-item').data('index');
    }

    xbox.remove_group_control_item($btn, index);
    xbox._remove_group_item($btn, index);

    if( sort_items ){
      setTimeout(function () {
        $group_wrap.trigger('sort_group_items', [index]);
        $group_control.children('.xbox-group-control-item').eq(0).trigger('click');
        $group_control.trigger('sort_group_control_items');
      }, xbox.delays.removeItem.events);
    }
  };

  xbox.remove_group_items = function (items) {
    if( ! items.length ){
      return;
    }
    var $row, $group_wrap, $group_control;
    var min_index = 1000;
    setTimeout(function () {
      $(items).each(function(i, $element){
        var index = $element.data('index');
        if( index < min_index ){
          min_index = index;
        }
        if( i == 0){
          $row = $element.closest('.xbox-type-group');
          $group_wrap = $row.find('.xbox-group-wrap').first();
          $group_control = xbox.get_group_control($element);
        }
        xbox.remove_group_item($element, false)
      });
    }, xbox.delays.removeItem.confirm);

    setTimeout(function () {
      $group_wrap.trigger('sort_group_items', [min_index]);
      $group_control.children('.xbox-group-control-item').eq(0).trigger('click');
      $group_control.trigger('sort_group_control_items');
    }, xbox.delays.removeItem.events);
  };

  xbox.remove_group_control_item = function ($btn, index) {
    var $group_control = xbox.get_group_control($btn);
    var $control_item = xbox.get_control_item($group_control, index);
    $control_item.fadeOut(xbox.delays.removeItem.fade, function () {
      $control_item.remove();
    });
  };

  xbox._remove_group_item = function ($btn, index) {
    var $row = $btn.closest('.xbox-type-group');
    var $group_wrap = $row.find('.xbox-group-wrap').first();
    $row.trigger('xbox_before_remove_group_item');
    var $item = $group_wrap.children('.xbox-group-item[data-index="'+index+'"]');
    var type = $item.data('type');
    $item.fadeOut(xbox.delays.removeItem.fade, function () {
      $item.remove();
      // $group_wrap.trigger('sort_group_items', [index]);
      $row.trigger('xbox_after_remove_group_item', [index, type]);
      // $group_control.children('.xbox-group-control-item').eq(0).trigger('click');
    });
  };

  xbox.on_click_group_control_item = function (event) {
    var $control_item = $(this);
    xbox.active_control_item(event, $control_item);
    return false;
  };

  xbox.active_control_item = function (event, $control_item) {
    var $group_control = $control_item.parent();
    var index = $control_item.index();
    var $group = $group_control.closest('.xbox-type-group');
    var $group_wrap = $group.find('.xbox-group-wrap').first();
    var $group_item = xbox.get_group_item($group_wrap, index);
    var $old_control_item = $group_control.children('.xbox-active');

    $group_control.children('.xbox-group-control-item').removeClass('xbox-active');
    $control_item.addClass('xbox-active');

    $group_wrap.children('.xbox-group-item').removeClass('xbox-active');
    $group_item.addClass('xbox-active');

    var args = {
      $group_item: $group_item,
      $control_item: $control_item,
      index: $group_item.data('index'),
      type: $group_item.data('type'),
      event: event,
      old_index: $old_control_item.data('index'),
    };

    setTimeout(function(){
      $group.trigger('xbox_on_active_group_item', [args]);
      xbox.update_fields_on_item_active($group_item);
    }, 10);//Retardar un poco para posibles eventos on click desde otras aplicaciones
    return false;
  };

  xbox.update_fields_on_item_active = function ($group_item) {
    //Init WP Editor
    $group_item.find('.wp-editor-wrap.init-wp-editor').each(function (index, el) {
      xbox.init_wp_editor($(el));
    });
  };

  xbox.sort_group_control_items = function (event) {
    var $group_control = $(event.target);
    var row_level = parseInt($group_control.closest('.xbox-row').data('row-level'));
    $group_control.children('.xbox-group-control-item').each(function (index, item) {
      xbox.update_group_control_item($(item), index, row_level);
    });
  };

  xbox.sort_group_items = function (event, start_index, end_index) {
    start_index = parseInt(start_index);
    var $group_wrap = $(event.target);
    $group_wrap.trigger('xbox_before_sort_group');
    var row_level = parseInt($group_wrap.closest('.xbox-row').data('row-level'));
    end_index = end_index !== undefined ? parseInt(end_index) + 1 : undefined;

    var $items = $group_wrap.children('.xbox-group-item');
    var $items_to_sort = $items.slice(start_index, end_index);

    $items_to_sort.each(function (i, group_item) {
      var index = start_index + i;
      xbox.update_attributes($(group_item), index, row_level);
      //Destroy WP Editors
      $(group_item).find('.wp-editor-wrap').each(function (index, el) {
        xbox.destroy_wp_editor($(el));
      });
    });
    $group_wrap.trigger('xbox_after_sort_group');
  };

  xbox.update_group_control_item = function ($item, index, row_level) {
    $item.data('index', index).attr('data-index', index);
    $item.find('.xbox-info-order-item').text('#' + (index + 1));
    var value;
    if ($item.find('.xbox-inner input').length) {
      value = $item.find('.xbox-inner input').val();
      $item.find('.xbox-inner input').val(value.replace(/(#\d+)/g, '#' + (index + 1)));
    }

    //Cambiar names
    $item.find('*[name]').each(function (i, item) {
      xbox.update_name_ttribute($(item), index, row_level);
    });
  };

  xbox.update_attributes = function ($new_item, index, row_level) {
    $new_item.data('index', index).attr('data-index', index);

    $new_item.find('*[name]').each(function (i, item) {
      xbox.update_name_ttribute($(item), index, row_level);
    });

    $new_item.find('*[id]').each(function (i, item) {
      xbox.update_id_attribute($(item), index, row_level);
    });

    $new_item.find('label[for]').each(function (i, item) {
      xbox.update_for_attribute($(item), index, row_level);
    });

    $new_item.find('*[data-field-name]').each(function (i, item) {
      xbox.update_data_name_attribute($(item), index, row_level);
    });

    $new_item.find('*[data-editor]').each(function (i, item) {
      xbox.update_data_editor_attribute($(item), index, row_level);
    });

    $new_item.find('*[data-wp-editor-id]').each(function (i, item) {
      xbox.update_data_wp_editor_id_attribute($(item), index, row_level);
    });

    xbox.set_checked_inputs($new_item, row_level);
  };

  xbox.set_checked_inputs = function ($group_item, row_level) {
    $group_item.find('.xbox-field').each(function (iterator, item) {
      if ($(item).hasClass('xbox-has-icheck') || $(item).closest('.xbox-type-image_selector').length) {
        var $input = $(item).find('input[type="radio"], input[type="checkbox"]');
        $input.each(function (i, input) {
          if ($(input).parent('div').hasClass('checked')) {
            $(input).attr('checked', 'checked').prop('checked', true);
          } else {
            $(input).removeAttr('checked').prop('checked', false);
          }
          if ($(input).next('img').hasClass('xbox-active')) {
            $(input).attr('checked', 'checked').prop('checked', true);
          }
        });
      }
    });
  };

  xbox.update_name_ttribute = function ($el, index, row_level) {
    var old_name = $el.attr('name');
    var new_name = '';
    if (typeof old_name !== 'undefined') {
      new_name = xbox.nice_replace(/(\[\d+\])/g, old_name, '[' + index + ']', row_level);
      $el.attr('name', new_name);
    }
  };

  xbox.update_id_attribute = function ($el, index, row_level) {
    var old_id = $el.attr('id');
    var new_id = '';
    if (typeof old_id !== 'undefined') {
      new_id = xbox.nice_replace(/(__\d+__)/g, old_id, '__' + index + '__', row_level);
      $el.attr('id', new_id);
    }
  };

  xbox.update_for_attribute = function ($el, index, row_level) {
    var old_for = $el.attr('for');
    var new_for = '';
    if (typeof old_for !== 'undefined') {
      new_for = xbox.nice_replace(/(__\d+__)/g, old_for, '__' + index + '__', row_level);
      $el.attr('for', new_for);
    }
  };
  xbox.update_data_name_attribute = function ($el, index, row_level) {
    var old_data = $el.attr('data-field-name');
    var new_data = '';
    if (typeof old_data !== 'undefined') {
      new_data = xbox.nice_replace(/(\[\d+\])/g, old_data, '[' + index + ']', row_level);
      $el.attr('data-field-name', new_data);
    }
  };

  xbox.update_data_editor_attribute = function ($el, index, row_level) {
    var old_data = $el.attr('data-editor');
    var new_data = '';
    if (typeof old_data !== 'undefined') {
      new_data = xbox.nice_replace(/(__\d+__)/g, old_data, '__' + index + '__', row_level);
      $el.attr('data-editor', new_data);
    }
  };
  xbox.update_data_wp_editor_id_attribute = function ($el, index, row_level) {
    var old_data = $el.attr('data-wp-editor-id');
    var new_data = '';
    if (typeof old_data !== 'undefined') {
      new_data = xbox.nice_replace(/(__\d+__)/g, old_data, '__' + index + '__', row_level);
      $el.attr('data-wp-editor-id', new_data);
    }
  };


  ////////////////////////
  xbox.remove_item_sortable_list = function( e ){
    var fields = xbox.get_select_sortable_fields($(e.target));
    var delete_id = $(e.target).closest('.xbox-item-sort').data('key');
    fields.$selectableRow.find('a.ui.label[data-value="'+delete_id+'"] .delete').trigger('click');
  };
  xbox.on_change_fields_select_sortable = function( $select_sortable ){
    xbox.fill_sortable_items_array($select_sortable);
    xbox.on_change_sort_by_select_sortable($select_sortable);
    xbox.on_update_select_sortable($select_sortable);
  };

  xbox.on_change_sort_by_select_sortable = function ($select_sortable) {
    var fields = xbox.get_select_sortable_fields($select_sortable);
    fields.$sortByRow.find('.xbox-element').on('xbox_changed_value', function(event, value){
      if( value == 'name_asc' ){
        xbox.sort_by_name_items_select_sortable(fields, 1);
      } if( value == 'name_desc' ){
        xbox.sort_by_name_items_select_sortable(fields, -1);
      } else if( value == 'date_asc' ){
        xbox.sort_by_date_items_select_sortable(fields, 1);
      } else if( value == 'date_desc' ){
        xbox.sort_by_date_items_select_sortable(fields, -1);
      } else if( value == 'random' ){
        xbox.sort_by_random_items_select_sortable(fields);
      }
    });
  };

  xbox.sort_by_name_items_select_sortable = function (fields, order) {
    fields.$sortableList.data('sortable-array').sort(function (a, b) {
      if(a.name > b.name) { return order*(1); }
      if(a.name < b.name) { return order*(-1); }
      return 0;
    });
    xbox.update_sortable_items_by_action(fields);
  };

  xbox.sort_by_date_items_select_sortable = function (fields, order) {
    fields.$sortableList.data('sortable-array').sort(function (a, b) {
      if(a.date > b.date) { return order*(1); }
      if(a.date < b.date) { return order*(-1); }
      return 0;
    });
    xbox.update_sortable_items_by_action(fields);
  };

  xbox.sort_by_random_items_select_sortable = function (fields) {
    var array = fields.$sortableList.data('sortable-array');
    var currentIndex = array.length, temporaryValue, randomIndex;
    while (0 !== currentIndex) {
      randomIndex = Math.floor(Math.random() * currentIndex);
      currentIndex -= 1;
      temporaryValue = array[currentIndex];
      array[currentIndex] = array[randomIndex];
      array[randomIndex] = temporaryValue;
    }
    fields.$sortableList.data('sortable-array', array);
    xbox.update_sortable_items_by_action(fields);
  };

  xbox.on_update_select_sortable = function ($select_sortable) {
    $select_sortable.on('xbox_changed_value', function(event, value){
    });
    $select_sortable.on('xbox_dropdown_added_item', function(event, addedValue, addedText, $addedChoice){
      xbox.on_add_item_select_sortable($select_sortable, addedValue);
    });
    $select_sortable.on('xbox_dropdown_removed_item', function(event, removedValue, removedText, $removedChoice){
      xbox.on_remove_item_select_sortable($select_sortable, removedValue);
    });
  };

  xbox.on_add_item_select_sortable = function ($select_sortable, key) {
    var fields = xbox.get_select_sortable_fields($select_sortable);
    var created = xbox.create_item_to_sort_select_sortable(fields, key);
    if( created ){
      fields.$sortableList.trigger('update_sortable_items');
    }
  };

  xbox.create_item_to_sort_select_sortable = function (fields, key) {
    var last_index = xbox.get_last_index_sortable_item(fields);
    var item_obj = xbox.get_item_obj_select_sortable(fields, key);
    if( is_empty(item_obj) ){
      return false;
    }
    var $item = $('<div>', { 'class': 'xbox-item-sort', 'data-key': key, 'data-index': last_index + 1 });
    var $img = $('<img>', { 'class': 'xbox-item-sort-img', 'src': item_obj.image_url });
    var $name = $('<span>', { 'class': 'xbox-item-sort-name', text: item_obj.name  });
    var $number = $('<span>', { 'class': 'xbox-item-sort-number', text:  last_index + 2 });
    var $remove_icon = $('<i>', { 'class': 'xbox-icon xbox-icon-close xbox-item-sort-remove', title: 'Remove' });

    var $edit_link = '';
    if( fields.$sortableList.data('show-edit-link') ){
      var url = XBOX_JS.admin_url.replace(/\/$/, "")+'/post.php?post='+key+'&action=edit';
      $edit_link = $('<a>', { 'class': 'xbox-item-sort-edit', href: url, target: '_blank', title: 'Edit', html: "<i class='xbox-icon xbox-icon-pencil'></i>" });
    }
    if( item_obj.image_url ){
      $item.append($img, $name, $number, $remove_icon, $edit_link);
    } else {
      $item.append($name, $number, $remove_icon, $edit_link);
    }
    fields.$sortableList.append($item);
    return true;
  };

  xbox.get_last_index_sortable_item = function (fields) {
    return fields.$sortableList.find('.xbox-item-sort').length-1;
  };

  xbox.get_item_obj_select_sortable = function (fields, key) {
    var items_data = fields.$selectableRow.find('.xbox-element').data('items_data');
    if( items_data ){
      return items_data[key]
    }
    return undefined;
  };

  xbox.on_remove_item_select_sortable = function ($select_sortable, key) {
    var fields = xbox.get_select_sortable_fields($select_sortable);
    fields.$sortableList.find('[data-key='+key+']').remove();
    fields.$sortableList.trigger('update_sortable_items');
  };

  xbox.update_sortable_items = function (event) {
    //console.log("UPDATE update_sortable_items");
    var $sortableList = $(event.target);
    $sortableList.children('.xbox-item-sort').each(function (index, item) {
      xbox.update_sortable_item($(item), index);
    });
    $sortableList.trigger('after_update_sortable_items');
  };

  xbox.after_sort_sortable_items = function (event) {
    var $sortableList = $(event.target);
    var fields = xbox.get_select_sortable_fields($sortableList);
    xbox.set_field_value(fields.$sortByRow.find('.xbox-field'), 'drag_drop');
  };

  xbox.update_sortable_items_by_action = function (fields) {
    //console.log("update_sortable_items_by_action");
    fields.$sortableList.children('.xbox-item-sort').each(function (index, item) {
      xbox.update_sortable_item($(item), index, fields.$sortableList.data('sortable-array')[index]);
    });
    fields.$sortableList.trigger('after_update_sortable_items');
  };

  xbox.update_sortable_item = function ($item, index, obj ) {
    $item.data('index', index).attr('data-index', index);
    $item.find('.xbox-item-sort-number').text(index+1);
    if( obj ){
      $item.data('key', obj.key).attr('data-key', obj.key);
      $item.find('.xbox-item-sort-img').attr('src', obj.image_url);
      $item.find('.xbox-item-sort-name').text(obj.name);
    }
  };

  xbox.after_update_sortable_items = function (event) {
    var $sortableList = $(event.target);
    xbox.fill_sortable_input_field($sortableList);
    xbox.fill_sortable_items_array($sortableList);
  };

  xbox.fill_sortable_input_field = function ($sortableList) {
    var keys = xbox.get_sortable_keys($sortableList);
    var $input_field = $sortableList.closest('.xbox-row').find('.xbox-element');
    $input_field.val(keys.join(','));
    $input_field.trigger('input');//Importante para qque actualize
  };

  xbox.fill_sortable_items_array = function ($sortableList) {
    var fields = xbox.get_select_sortable_fields($sortableList);
    var keys = xbox.get_sortable_keys(fields.$sortableList);
    var items_data = fields.$selectableRow.find('.xbox-element').data('items_data');
    //console.log("items_data", items_data);
    //console.log("keys", keys);
    var items = [];
    keys.forEach(function(key, index){
      items.push({
        key: key,
        name: items_data[key].name,
        date: items_data[key].date,
        image_url: items_data[key].image_url,
      });
    });
    fields.$sortableList.data('sortable-array', items);
  };

  xbox.get_select_sortable_fields = function ($select_sortable) {
    var selectable_field_id = $select_sortable.closest('.xbox-field').find('.xbox-element').data('field-selectable');
    var sort_by_field_id = $select_sortable.closest('.xbox-field').find('.xbox-element').data('field-sort_by');
    var sortable_field_id = $select_sortable.closest('.xbox-field').find('.xbox-element').data('field-sortable');
    var $context = $select_sortable.closest('.xbox');
    if( xbox.inside_group_item($select_sortable) ){
      $context = $select_sortable.closest('.xbox-group-item');
    }
    var $selectable_row = $context.find('[data-field-id="'+selectable_field_id+'"]').first();
    var $sort_by_row = $context.find('[data-field-id="'+sort_by_field_id+'"]').first();
    var $sortable_row = $context.find('[data-field-id="'+sortable_field_id+'"]').first();
    var sortable_list = $sortable_row.find('.xbox-sortable-items').first();
    return {
      selectableFieldId: selectable_field_id,
      $selectableRow: $selectable_row,
      sortByFieldId: sort_by_field_id,
      $sortByRow: $sort_by_row,
      sortableFieldId: sortable_field_id,
      $sortableRow: $sortable_row,
      $sortableList: sortable_list
    }
  };

  xbox.get_sortable_keys = function ($sortableList) {
    var keys = [];
    $sortableList.find('.xbox-item-sort').each(function(index, item){
      keys.push($(item).data('key'));
    });
    return keys;
  };

  xbox.inside_group_item = function ($target) {
    var $group_item = $target.closest('.xbox-group-item');
    return !!$group_item.length;
  };


  //////////////////////////////////////


  xbox.set_default_values = function ($group) {
    $group.find('*[data-default]').each(function (iterator, item) {
      var $field = $(item);
      var default_value = $field.data('default');
      if ($field.closest('.xbox-type-number').length) {
        xbox.set_field_value($field, default_value);
      } else {
        xbox.set_field_value($field, default_value);
      }
    });
  };

  xbox.set_field_value = function ($field, value, extra_value, update_initial_values) {
    if( !$field.length ){
      return;
    }
    var $input, array;
    var type = $field.closest('.xbox-row').data('field-type');
    value = is_empty(value) ? '' : value;

    switch (type) {
      case 'number':
        var $input = $field.find('input.xbox-element');
        //Ctrl + z functionality
        xbox.update_prev_values($input, value, update_initial_values);

        if (value == $input.val()) {
          return;
        }

        $input.attr('value', value).val(value);
        var unit = extra_value === undefined ? $input.data('default-unit') : extra_value;
        var $unit_number = $field.find('input.xbox-unit-number');
        //if( unit != $unit_number.val() ){//No verificar porque unit activa el evento "input" del número
          $unit_number.attr('value', unit).trigger('change');
        //}
        unit = unit || '#';
        $field.find('.xbox-unit span').text(unit);
        break;

      case 'text':
      case 'hidden':
      case 'colorpicker':
      case 'date':
      case 'time':
        var $input = $field.find('input.xbox-element');

        //Ctrl + z functionality
        xbox.update_prev_values($input, value, update_initial_values);

        if (value == $input.val()) {
          return;
        }

        //Importante que tenga tanto val como attr value
        $input.attr('value', value).val(value);

        if (type == 'colorpicker') {
          xbox.reset_colorpicker($field, value);
          $input.trigger('input');
        } else {
          $input.trigger('change').trigger('input');
        }
        break;

      case 'file':
      case 'oembed':
        var $input = $field.find('input.xbox-element');

        //Ctrl + z functionality
        xbox.update_prev_values($input, value, update_initial_values);

        $input.attr('value', value).trigger('change').trigger('input');
        $field.find('.xbox-wrap-preview').html('');
        break;

      case 'image':
        $field.find('input.xbox-element').attr('value', value);
        $field.find('img.xbox-element-image').attr('src', value);
        if (is_empty(value)) {
          $field.find('img.xbox-element-image').hide().next('.xbox-remove-preview').hide();
        }
        break;

      case 'select':
        var $input = $field.find('.xbox-element input[type="hidden"]');

        //Ctrl + z functionality
        xbox.update_prev_values($input, value, update_initial_values);

        var $dropdown = $field.find('.ui.selection.dropdown');
        var max_selections = parseInt($dropdown.data('max-selections'));
        $dropdown.dropdownXbox('clear');
        if (max_selections > 1 && $dropdown.hasClass('multiple')) {
          $dropdown.dropdownXbox('set selected', value.split(','));
        } else {
          $dropdown.dropdownXbox('set selected', value);
        }
        break;

      case 'switcher':
        $input = $field.find('input');

        //Ctrl + z functionality
        xbox.update_prev_values($input, value, update_initial_values);

        if ($input.val() !== value) {
          if ($input.next().hasClass('xbox-sw-on')) {
            $input.xboxSwitcher('set_off');
          } else {
            $input.xboxSwitcher('set_on');
          }
        }
        break;

      case 'wp_editor':
        var $textarea = $field.find('textarea.wp-editor-area');
        $textarea.val(value);
        var wp_editor = tinymce.get($textarea.attr('id'));
        if (wp_editor) {
          wp_editor.setContent(value);
        }
        break;

      case 'textarea':
        $field.find('textarea').val(value).trigger('input');
        break;

      case 'code_editor':
        $field.find('textarea.xbox-element').text(value);
        var editor = ace.edit($field.find('.xbox-code-editor').attr('id'));
        editor.setValue(value);
        break;

      case 'icon_selector':
        $field.find('input.xbox-element').attr('value', value).trigger('change');
        var html = '';
        if (value.indexOf('.svg') > -1) {
          html = '<img src="' + value + '">';
        } else {
          html = '<i class="' + value + '"></i>';
        }
        $field.find('.xbox-icon-active').html(html);
        break;

      case 'image_selector':
        value = value.toString().toLowerCase();
        $input = $field.find('input');

        if (!$input.closest('.xbox-image-selector').data('image-selector').like_checkbox) {
          if (is_empty($input.filter(':checked').val())) {
            return;
          }
          if ($input.filter(':checked').val().toLowerCase() != value) {
            $input.filter(function (i) {
              return $(this).val().toLowerCase() == value;
            }).trigger('click.img_selector');
          }
        } else {
          if (get_value_checkbox($input, ',').toLowerCase() != value) {
            $input.first().trigger('img_selector_disable_all');
            array = value.replace(/ /g, '').split(',');
            $.each(array, function (index) {
              $input.filter(function (i) {
                return $(this).val().toLowerCase() == array[index];
              }).trigger('click.img_selector');
            });
          }
        }
        break;

      case 'checkbox':
      case 'radio':
        value = value.toString().toLowerCase();
        if ($field.hasClass('xbox-has-icheck') && $field.find('.init-icheck').length) {
          $input = $field.find('input');
          if (type == 'radio') {
            if (is_empty($input.filter(':checked').val())) {
              return;
            }
            $input.iCheck('uncheck');
            //if( $input.filter(':checked').val().toLowerCase() != value ){
            $input.filter(function (i) {
              return $(this).val().toLowerCase() == value;
            }).iCheck('check');
            //}
          } else if (type == 'checkbox') {
            if (get_value_checkbox($input, ',').toLowerCase() != value) {
              $input.iCheck('uncheck');
              array = value.replace(/ /g, '').split(',');
              $.each(array, function (index) {
                $input.filter(function (i) {
                  return $(this).val().toLowerCase() == array[index];
                }).iCheck('check');
              });
            }
          }
        }
        break;
    }
  };

  xbox.update_prev_values = function ($input, value, update_initial_values) {
    if( update_initial_values ){
      $input.attr('data-initial-value', value).data('initial-value', value);
      // $input.attr('data-prev-value', value).data('prev-value', value);
      // $input.attr('data-temp-value', value).data('temp-value', value);
    } else {
      //Va un poco lento cuando hay múltiples cambios a la vez
      //Ctrl + z functionality
      // var tempValue = $input.data('temp-value');
      // if( tempValue != value ){
      //   $input.attr('data-prev-value', tempValue).data('prev-value', tempValue);
      //   $input.attr('data-temp-value', value).data('temp-value', value);
      // }
    }
  };

  xbox.nice_replace = function (regex, string, replace_with, row_level, offset) {
    offset = offset || 0;
    //http://stackoverflow.com/questions/10584748/find-and-replace-nth-occurrence-of-bracketed-expression-in-string
    var n = 0;
    string = string.replace(regex, function (match, i, original) {
      n++;
      return (n === row_level + offset) ? replace_with : match;
    });
    return string;
  };

  xbox.get_object_id = function () {
    return $('.xbox').data('object-id');
  };

  xbox.get_object_type = function () {
    return $('.xbox').data('object-type');
  };

  xbox.get_group_object_values = function ($group_item) {
    var values = $group_item.find('input[name],select[name],textarea[name]').serializeArray();
    return values;
  };

  xbox.get_group_values = function ($group_item) {
    var object_values = xbox.get_group_object_values($group_item);
    var values = {};
    $.each(object_values, function (index, field) {
      values[field.name] = field.value;
    });
    return values;
  };

  xbox.get_xbox_values = function ($xbox) {
    var object_values = xbox.get_group_object_values($xbox);
    var values = {};
    var full_values = {};
    $.each(object_values, function (index, field) {
      var name = field.name;
      if( name.indexOf('[]', name.length - 2) !== -1 ){//for checkboxs
        full_values[name] = full_values[name] ? full_values[name] + ','+field.value : field.value;
      } else {
        full_values[name] = field.value;
      }
    });
    $.each(full_values, function (name, value) {
      //Checkbox name is like prefix_test-checkbox[]
      if( name.indexOf('[]', name.length - 2) !== -1 ){
        values[name.slice(0,-2)] = value;
      } else {
        values[name] = value;
      }
      // name = name.slice(0, -1);//Remove "[" and "]"
      // if (name.indexOf('][') === -1) {
      //   values[name] = value;
      // } else {
      //   name = name.replace('][', '');
      //   values[name] = value.split(',');
      // }
    });
    return values;
  };

  xbox.get_field_value = function ($xbox, field_name, default_value) {
    default_value = default_value || '';
    if( field_name instanceof $){
      field_name = field_name.closest('.xbox-row').data('field-id');
    }
    field_name = xbox.parse_field_name($xbox, field_name);
    var get_xbox_values = xbox.get_xbox_values($xbox);
    if( get_xbox_values[field_name] ){
      return get_xbox_values[field_name];
    }
    return default_value;
  };

  xbox.parse_field_name = function ($xbox, field_name) {
    var prefix = xbox.get_prefix($xbox);
    if( field_name.indexOf(prefix) == -1 ){
      field_name = prefix + field_name;
    }
    return field_name;
  };

  xbox.compare_values_by_operator = function (value1, operator, value2) {
    switch (operator) {
      case '<':
        return value1 < value2;
      case '<=':
        return value1 <= value2;
      case '>':
        return value1 > value2;
      case '>=':
        return value1 >= value2;
      case '==':
      case '=':
        return value1 == value2;
      case '!=':
        return value1 != value2;
      default:
        return false;
    }
    return false;
  };

  xbox.add_style_attribute = function ($element, new_style) {
    var old_style = $element.attr('style') || '';
    $element.attr('style', old_style + '; ' + new_style);
  };

  xbox.is_image_file = function (value) {
    value = $.trim(value.toString());
    return (value.match(/\.(jpeg|jpg|gif|png)$/) !== null);
  };

  xbox.is_group_table_layout = function ($target) {
    var $group_row = $target.closest('.xbox-type-group');
    return $group_row.hasClass('xbox-group-table-layout');
  };

  xbox.close_alert_message = function (event) {
    $(event.target).closest('.xbox-message').fadeOut(200, function(){
      $(this).remove();
    });
  };


  //Funciones privadas
  function is_empty(value) {
    return (value === undefined || value === false || $.trim(value).length === 0);
  }

  function get_class_starts_with($elment, starts_with) {
    return $.grep($elment.attr('class').split(" "), function (v, i) {
      return v.indexOf(starts_with) === 0;
    }).join();
  }

  function get_value_checkbox($elment, separator) {
    separator = separator || ',';
    if ($elment.attr('type') != 'checkbox') {
      return '';
    }
    var value = $elment.filter(':checked').map(function () {
      return this.value;
    }).get().join(separator);
    return value;
  }

  function viewport() {
    var e = window, a = 'inner';
    if (!('innerWidth' in window)) {
      a = 'client';
      e = document.documentElement || document.body;
    }
    return { width: e[a + 'Width'], height: e[a + 'Height'] };
  }


  //Debug
  function c(msg) {
    console.log(msg);
  }

  function cc(msg, msg2) {
    console.log(msg, msg2);
  }

  //Document Ready
  $(function () {
    xbox.init();
  });

  return xbox;

})(window, document, jQuery);


/**
 * jQuery alterClass plugin
 *
 * Remove element classes with wildcard matching. Optionally add classes:
 *   $( '#foo' ).alterClass( 'foo-* bar-*', 'foobar' )
 *
 * Copyright (c) 2011 Pete Boere (the-echoplex.net)
 * Free under terms of the MIT license: http://www.opensource.org/licenses/mit-license.php
 *
 */
(function ($) {
  $.fn.alterClass = function (removals, additions) {
    var self = this;
    if (removals.indexOf('*') === -1) {
      // Use native jQuery methods if there is no wildcard matching
      self.removeClass(removals);
      return !additions ? self : self.addClass(additions);
    }
    var patt = new RegExp('\\s' +
      removals.replace(/\*/g, '[A-Za-z0-9-_]+').split(' ').join('\\s|\\s') +
      '\\s', 'g');
    self.each(function (i, it) {
      var cn = ' ' + it.className + ' ';
      while (patt.test(cn)) {
        cn = cn.replace(patt, ' ');
      }
      it.className = $.trim(cn);
    });
    return !additions ? self : self.addClass(additions);
  };
})(jQuery);

